#ifndef XEUS_XLANG_INTERPRETER_HPP
#define XEUS_XLANG_INTERPRETER_HPP

#ifdef __GNUC__
    #pragma GCC diagnostic push
    #pragma GCC diagnostic ignored "-Wattributes"
#endif

#include <string>
#include <memory>

#if (WIN32)
#include <winsock2.h>
#include <windows.h>
#else
#include <netinet/in.h>
#include <sys/socket.h>
#include <unistd.h>
#endif

#include "nlohmann/json.hpp"

#include "xeus_xlang_config.hpp"
#include "xeus/xinterpreter.hpp"

namespace httplib{ class Client;};

namespace nl = nlohmann;

namespace xeus_xlang
{
    class XEUS_XLANG_API xlang_interpreter : public xeus::xinterpreter
	{
	public:

		xlang_interpreter() = default;
		virtual ~xlang_interpreter() = default;

		void set_exe_path(const std::string path){ exePath  = path; };
		void set_xlang_path(const std::string path){ xlangPath  = path; };
	private:

		void configure_impl() override;

        void execute_request_impl(xeus::xinterpreter::send_reply_callback cb,
                                  int execution_counter,
                                  const std::string &code,
                                  xeus::execute_request_config config,
                                  nl::json user_expressions) override;

        void connect_xlang(std::string &inCodeLower, size_t cmd_pos, xeus::xinterpreter::send_reply_callback &cb, int execution_counter);

        void run_cell_code(xeus::xinterpreter::send_reply_callback &cb, int execution_counter, const std::string &code);
		void run_command(xeus::xinterpreter::send_reply_callback &cb, int execution_counter, const std::string &code);

        nl::json complete_request_impl(const std::string &code,
                                       int cursor_pos) override;

        nl::json inspect_request_impl(const std::string &code,
                                      int cursor_pos,
                                      int detail_level) override;

        nl::json is_complete_request_impl(const std::string &code) override;

        nl::json kernel_info_request_impl() override;

		void shutdown_request_impl() override;
		void close_xlang();
		void create_xlang(xeus::xinterpreter::send_reply_callback cb, int execution_counter, int port);

		std::string exePath;
		std::string xlangPath;
		std::string addr;
		bool isConnected = false;
		httplib::Client* client = nullptr;
		bool xlangCreated = false;
#if (WIN32)
        PROCESS_INFORMATION process_info;
#else
		pid_t process_id;
#endif

	};
}

#ifdef __GNUC__
    #pragma GCC diagnostic pop
#endif

#endif
